<template>
  <div class="traffic-stats">
    <!-- 统计卡片 -->
    <el-row :gutter="20" class="stat-cards">
      <el-col :span="6" v-for="(stat, index) in statistics" :key="index">
        <el-card shadow="hover" :body-style="{ padding: '20px' }">
          <div class="stat-card">
            <div class="stat-icon" :style="{ color: stat.color }">
              <el-icon>
                <component :is="stat.icon" />
              </el-icon>
            </div>
            <div class="stat-info">
              <div class="stat-title">{{ stat.title }}</div>
              <div class="stat-value" :style="{ color: stat.color }">
                {{ stat.value }}
                <span class="stat-unit">{{ stat.unit }}</span>
              </div>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 实时流量图表 -->
    <el-card class="chart-card">
      <template #header>
        <div class="card-header">
          <span>实时流量监控</span>
          <div class="header-controls">
            <el-radio-group v-model="chartMetric" size="small" @change="switchMetric">
              <el-radio-button label="qps">QPS</el-radio-button>
              <el-radio-button label="responseTime">响应时间</el-radio-button>
              <el-radio-button label="errorRate">错误率</el-radio-button>
            </el-radio-group>
          </div>
        </div>
      </template>
      <div ref="chartRef" style="height: 400px"></div>
    </el-card>

    <!-- API监控表格 -->
    <el-card class="table-card" v-loading="loading">
      <template #header>
        <div class="card-header">
          <span>API 接口监控</span>
          <div class="header-controls">
            <el-select v-model="timeRange" size="small" @change="handleTimeRangeChange">
              <el-option label="最近1分钟" value="1m" />
              <el-option label="最近5分钟" value="5m" />
              <el-option label="最近15分钟" value="15m" />
            </el-select>
            <el-button
                type="primary"
                size="small"
                @click="fetchTrafficData"
                :loading="loading"
            >
              <el-icon><Refresh /></el-icon>
              刷新
            </el-button>
          </div>
        </div>
      </template>

      <el-table
          :data="trafficData"
          style="width: 100%"
          :stripe="true"
          :border="true"
          height="400"
      >
        <el-table-column prop="uri" label="接口路径" min-width="200" show-overflow-tooltip>
          <template #default="scope">
            <el-tooltip :content="scope.row.uri" placement="top">
              <span>{{ scope.row.uri }}</span>
            </el-tooltip>
          </template>
        </el-table-column>

        <el-table-column prop="qps" label="QPS" width="120" sortable>
          <template #default="scope">
            <span :class="getQpsClass(scope.row.qps)">
              {{ formatNumber(scope.row.qps, 2) }}
            </span>
          </template>
        </el-table-column>

        <el-table-column prop="totalRequests" label="总请求数" width="120" sortable>
          <template #default="scope">
            {{ formatNumber(scope.row.totalRequests) }}
          </template>
        </el-table-column>

        <el-table-column prop="avgResponseTime" label="平均响应时间" width="150" sortable>
          <template #default="scope">
            <span :class="getResponseTimeClass(scope.row.avgResponseTime)">
              {{ formatNumber(scope.row.avgResponseTime, 2) }}ms
            </span>
          </template>
        </el-table-column>

        <el-table-column prop="successRate" label="成功率" width="180" sortable>
          <template #default="scope">
            <el-progress
                :percentage="Number(scope.row.successRate)"
                :status="getSuccessRateStatus(scope.row.successRate)"
                :stroke-width="8"
                :format="(val) => val.toFixed(2) + '%'"
            />
          </template>
        </el-table-column>

        <el-table-column prop="errorCount" label="错误数" width="120" sortable>
          <template #default="scope">
            <el-tag
                :type="scope.row.errorCount > 0 ? 'danger' : 'success'"
                :effect="scope.row.errorCount > 0 ? 'dark' : 'plain'"
            >
              {{ scope.row.errorCount }}
            </el-tag>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, shallowRef } from 'vue';
import { ElMessage } from 'element-plus';
import * as echarts from 'echarts';
import axios from 'axios';
import {
  Refresh,
  DataLine,
  Timer,
  Warning,
  Connection
} from '@element-plus/icons-vue';

// 配置常量
const PROMETHEUS_URL = 'http://localhost:9090';
const REFRESH_INTERVAL = 2000; // 2秒刷新一次
const CHART_POINTS = 60; // 保留60个数据点

// 状态变量
const loading = ref(false);
const timeRange = ref('1m');
const chartMetric = ref('qps');
const chartRef = ref();
const chart = shallowRef();
let refreshTimer: number;

// 图表数据
const chartData = ref({
  timestamps: [],
  values: [],
});

// 统计数据
const statistics = ref([
  {
    title: '当前QPS',
    value: '0',
    unit: '次/秒',
    icon: 'DataLine',
    color: '#409EFF'
  },
  {
    title: '今日总请求',
    value: '0',
    unit: '次',
    icon: 'Connection',
    color: '#67C23A'
  },
  {
    title: '平均响应时间',
    value: '0',
    unit: 'ms',
    icon: 'Timer',
    color: '#E6A23C'
  },
  {
    title: '错误率',
    value: '0',
    unit: '%',
    icon: 'Warning',
    color: '#F56C6C'
  }
]);

const trafficData = ref([]);

// 格式化数字
const formatNumber = (num: number, decimals = 0) => {
  if (isNaN(num)) return '0';
  if (num >= 10000) {
    return `${(num / 1000).toFixed(1)}k`;
  }
  return Number(num).toFixed(decimals);
};

// 获取QPS样式
const getQpsClass = (qps: number) => {
  if (qps >= 100) return 'qps-high';
  if (qps >= 50) return 'qps-medium';
  return 'qps-normal';
};

// 获取响应时间样式
const getResponseTimeClass = (time: number) => {
  if (time >= 500) return 'response-slow';
  if (time >= 100) return 'response-medium';
  return 'response-fast';
};

// 获取成功率状态
const getSuccessRateStatus = (rate: number) => {
  if (rate >= 99) return 'success';
  if (rate >= 95) return 'warning';
  return 'exception';
};

// 初始化图表
const initChart = () => {
  if (!chartRef.value) return;

  chart.value = echarts.init(chartRef.value);
  const option = {
    title: {
      text: '实时流量监控',
      left: 'center'
    },
    tooltip: {
      trigger: 'axis',
      formatter: function(params: any) {
        const time = new Date(params[0].value[0]).toLocaleTimeString();
        const value = params[0].value[1];
        const metric = chartMetric.value === 'qps' ? 'QPS' :
            chartMetric.value === 'responseTime' ? '响应时间(ms)' : '错误率(%)';
        return `${time}<br/>${metric}: ${value.toFixed(2)}`;
      }
    },
    grid: {
      left: '3%',
      right: '4%',
      bottom: '3%',
      containLabel: true
    },
    xAxis: {
      type: 'time',
      splitLine: { show: false }
    },
    yAxis: {
      type: 'value',
      splitLine: { lineStyle: { type: 'dashed' } }
    },
    series: [{
      name: 'metric',
      type: 'line',
      smooth: true,
      showSymbol: false,
      areaStyle: {
        opacity: 0.1
      },
      data: [],
      animation: false
    }]
  };
  chart.value.setOption(option);
};

// 更新图表
const updateChart = () => {
  if (!chart.value) return;

  const data = chartData.value.timestamps.map((time, index) => [
    time,
    chartData.value.values[index]
  ]);

  chart.value.setOption({
    series: [{
      data: data
    }]
  });
};

// 切换指标
const switchMetric = () => {
  chartData.value.timestamps = [];
  chartData.value.values = [];
  updateChart();
};

// 处理时间范围变化
const handleTimeRangeChange = () => {
  chartData.value.timestamps = [];
  chartData.value.values = [];
  fetchTrafficData();
};

// 获取Prometheus查询
const getPrometheusQueries = () => {
  const range = timeRange.value;
  return {
    requests: `sum(increase(gateway_requests_total[${range}])) by (route_id)`,
    responseTime: `sum(rate(gateway_duration_seconds_sum[${range}])) by (route_id) / sum(rate(gateway_duration_seconds_count[${range}])) by (route_id) * 1000`,
    errors: `sum(increase(gateway_status_total{status=~"4..|5.."}[${range}])) by (route_id)`,
    total: `sum(increase(gateway_status_total[${range}])) by (route_id)`,
    qps: `sum(rate(gateway_requests_total[${range}])) by (route_id)`
  };
};

// 获取指标值
const getMetricValue = (results: any[], routeId: string) => {
  const result = results?.find(r => r.metric.route_id === routeId);
  return result ? Number(result.value[1]) : 0;
};

// 获取流量数据
const fetchTrafficData = async () => {
  if (loading.value) return;
  loading.value = true;

  try {
    const queries = getPrometheusQueries();
    const results = await Promise.all(
        Object.entries(queries).map(async ([key, query]) => {
          const response = await axios.get(`${PROMETHEUS_URL}/api/v1/query`, {
            params: { query }
          });
          return [key, response.data.data.result];
        })
    );

    const metricsData = Object.fromEntries(results);

    // 更新表格数据
    trafficData.value = metricsData.requests.map(result => {
      const routeId = result.metric.route_id;

      const errors = getMetricValue(metricsData.errors, routeId);
      const total = getMetricValue(metricsData.total, routeId);
      const errorRate = total > 0 ? (errors / total * 100) : 0;
      const responseTime = getMetricValue(metricsData.responseTime, routeId);

      return {
        uri: routeId,
        totalRequests: Number(result.value[1]),
        avgResponseTime: responseTime || 0,
        successRate: 100 - errorRate,
        errorCount: Math.round(errors),
        qps: getMetricValue(metricsData.qps, routeId)
      };
    });

    // 更新统计信息
    const stats = {
      totalQps: 0,
      totalRequests: 0,
      totalErrors: 0,
      totalResponseTime: 0,
      validResponseTimes: 0
    };

    trafficData.value.forEach(data => {
      stats.totalQps += Number(data.qps) || 0;
      stats.totalRequests += data.totalRequests || 0;
      stats.totalErrors += data.errorCount || 0;
      if (data.avgResponseTime > 0) {
        stats.totalResponseTime += data.avgResponseTime;
        stats.validResponseTimes++;
      }
    });

    const avgResponseTime = stats.validResponseTimes > 0
        ? stats.totalResponseTime / stats.validResponseTimes
        : 0;

    const errorRate = stats.totalRequests > 0
        ? (stats.totalErrors / stats.totalRequests * 100)
        : 0;

    statistics.value = [
      {
        title: '当前QPS',
        value: stats.totalQps.toFixed(2),
        unit: '次/秒',
        icon: 'DataLine',
        color: '#409EFF'
      },
      {
        title: '今日总请求',
        value: formatNumber(stats.totalRequests),
        unit: '次',
        icon: 'Connection',
        color: '#67C23A'
      },
      {
        title: '平均响应时间',
        value: avgResponseTime.toFixed(2),
        unit: 'ms',
        icon: 'Timer',
        color: '#E6A23C'
      },
      {
        title: '错误率',
        value: errorRate.toFixed(2),
        unit: '%',
        icon: 'Warning',
        color: '#F56C6C'
      }
    ];

    // 更新图表数据
    const now = Date.now();
    let value = 0;

    switch (chartMetric.value) {
      case 'qps':
        value = stats.totalQps;
        break;
      case 'responseTime':
        value = avgResponseTime;
        break;
      case 'errorRate':
        value = errorRate;
        break;
    }

    chartData.value.timestamps.push(now);
    chartData.value.values.push(value);

    if (chartData.value.timestamps.length > CHART_POINTS) {
      chartData.value.timestamps.shift();
      chartData.value.values.shift();
    }

    updateChart();

  } catch (error) {
    console.error('获取流量数据失败:', error);
    ElMessage.error('获取数据失败，请检查 Prometheus 连接');
  } finally {
    loading.value = false;
  }
};

// 生命周期钩子
onMounted(() => {
  initChart();
  fetchTrafficData();
  refreshTimer = setInterval(fetchTrafficData, REFRESH_INTERVAL);

  window.addEventListener('resize', () => {
    chart.value?.resize();
  });
});

onUnmounted(() => {
  clearInterval(refreshTimer);
  chart.value?.dispose();
});
</script>


<style scoped>
.traffic-stats {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}

.stat-cards {
  margin-bottom: 20px;
}

.stat-card {
  display: flex;
  align-items: center;
  gap: 16px;
}

.stat-icon {
  font-size: 32px;
  padding: 16px;
  border-radius: 8px;
  background-color: #f5f7fa;
}

.stat-info {
  flex: 1;
}

.stat-title {
  font-size: 14px;
  color: #909399;
  margin-bottom: 8px;
}

.stat-value {
  font-size: 24px;
  font-weight: bold;
  line-height: 1;
}

.stat-unit {
  font-size: 12px;
  margin-left: 4px;
  color: #909399;
  font-weight: normal;
}

.chart-card,
.table-card {
  margin-bottom: 20px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.header-controls {
  display: flex;
  gap: 12px;
  align-items: center;
}

.qps-high { color: #F56C6C; }
.qps-medium { color: #E6A23C; }
.qps-normal { color: #67C23A; }

.response-fast { color: #67C23A; }
.response-medium { color: #E6A23C; }
.response-slow { color: #F56C6C; }

:deep(.el-card__header) {
  padding: 12px 20px;
  border-bottom: 1px solid #e4e7ed;
}

:deep(.el-card__body) {
  padding: 20px;
}

:deep(.el-table) {
  margin-top: 8px;
}

:deep(.el-progress-bar__inner) {
  transition: all 0.3s ease;
}

:deep(.el-progress-bar__outer) {
  background-color: #f5f7fa;
}

:deep(.el-tag) {
  width: 60px;
  text-align: center;
}
</style>
